-
Notifications
You must be signed in to change notification settings - Fork 350
feat formats: automatic serialization/deserialization based on Boost.PFR #469
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat formats: automatic serialization/deserialization based on Boost.PFR #469
Conversation
| return this->contents[index]; | ||
| }; | ||
|
|
||
| constexpr operator char&() const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wut
| }; | ||
| constexpr ConstexprString(std::array<char, Size> data) noexcept : contents(data) {}; | ||
| template <std::size_t OtherSize> | ||
| constexpr ConstexprString<Size + OtherSize> operator+(const ConstexprString<OtherSize>& other) const noexcept { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like operator+ is not really needed for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be used, for example, to generate constexpr SQL queries via Boost.PFR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I'll give it a second thought later
| template <std::size_t Size = 1> | ||
| struct ConstexprString { | ||
| static constexpr auto kSize = Size; | ||
| std::array<char, Size> contents; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<array> brings in <algorithm> in typical stdlib implementations, and that's a very heavy header. We try to minimize the usage of <array> in public headers
| template <typename T, typename Value> | ||
| inline bool Is(Value&& value) { | ||
| constexpr inline bool Is(Value&& value) { | ||
| if constexpr(std::is_convertible_v<T, std::int64_t>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
double and bool are convertible to int64_t
0784a5f to
a81e72c
Compare
| } // namespace impl | ||
|
|
||
| template <typename T, typename... Params> | ||
| class SerializationConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[big] After some internal discussion: we want to reduce the amount of template metaprogramming and make SerializationConfig value-based. Details of struct fields serialization and so on will be stored inside SerializationConfig itself, not inside its template parameters.
SerializationConfig should contain a tuple of FieldConfig for each field. FieldConfig should be parametrized with the parsed type. The config creation will look like this:
.With<"field">({.max_items = 10, .items = {.min = 42}})
With takes a single parameter of type FieldConfig<(type of "field")>, which is a struct with all optional members, like std::optional<std::size_t> max_items and FieldConfig<(type of items)> items. This config is assigned to the SerializationConfig's tuple element corresponding to "field".
FieldConfig should be able to be specialized for the parsed type. For example, FieldConfig will be specialized for array-like ranges to include min_items, max_items and items fields, and for numeric types to include min and max fields of appropriate type.
FieldConfig for structs should contain a single reference to the struct's SerializationConfig, which should be default-initialized with formats::universal::kSerialization<T>. The "reference" part is important, as it allows to create recursive structs.
Add a test that contains a simple recursive type:
struct Node {
int value;
std::vector<Node> children;
};Test universal serialization on it.
That's the gist of the vision for value-based serialization config. Feel free to ask questions here or in PM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functions will still be able to use if constexpr and alike by passing around const FieldConfig<T>& in template parameters. Remember that all those SerializationConfig and FieldConfig are stored inside variable templates, so it's possible to use addresses of those variables and their contents in templates, even in C++17
|
Continuing in #472 |
Example